package com.atguigu.core.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.atguigu.core.bean.R;
import com.atguigu.core.enumcode.ResultStatusCode;
import com.atguigu.core.feign.PayFeignApi;
import io.github.resilience4j.bulkhead.annotation.Bulkhead;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/order-gateway")
public class OrderFeignGatewayController {

    @Autowired
    private PayFeignApi payFeignApi;

    @GetMapping("/get/{id}")
    public R get(@PathVariable("id") Integer id) {

        return payFeignApi.gateway(id);

    }


    @GetMapping("/get/info")
    public R getMlb() {
        return R.ok().data(payFeignApi.getInfoByConsul());
    }

    /**
     * fallbackMethod 指定断路之后的回调方法
     *
     * @param id
     * @return
     */
    @GetMapping("/circuit/{id}")
    @CircuitBreaker(name = "cloud-payment-service", fallbackMethod = "circuitFallback")
    public R circuit(@PathVariable("id") Integer id) {
        System.out.println("--------- 调用开始：" + DateUtil.now());
        return payFeignApi.circuit(id);

    }

    private R circuitFallback(Throwable t) {
        return R.failure(ResultStatusCode.SYSTEM_ERR.getMsg());
    }

    /**
     * fallbackMethod 指定断路之后的回调方法
     *
     * @param id
     * @return
     */
    @GetMapping("/bulkhead/{id}")
    @Bulkhead(name = "cloud-payment-service", fallbackMethod = "bulkheadFallback", type = Bulkhead.Type.SEMAPHORE)
    public R bulkhead(@PathVariable("id") Integer id) {
        System.out.println("--------- 调用开始：" + DateUtil.now());
        return payFeignApi.bulkhead(id);

    }

    @GetMapping("/thread-pool-bulkhead/{id}")
    @Bulkhead(name = "cloud-payment-service", fallbackMethod = "threadpoolbulkheadFallback", type = Bulkhead.Type.THREADPOOL)
    public CompletableFuture<R> threadpoolbulkhead(@PathVariable("id") Integer id) {
        System.out.println("--------- 调用开始：" + DateUtil.now());


        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        return CompletableFuture.supplyAsync(() -> payFeignApi.bulkhead(id));


    }

    private R bulkheadFallback(Throwable t) {
        return R.failure("SEMAPHORE ERROR");
    }

    private CompletableFuture<R> threadpoolbulkheadFallback(Throwable t) {
        return CompletableFuture.supplyAsync(() ->
                R.failure(" threadpoolbulkhead ERROR"));
    }


    @GetMapping("/ratelimit/{id}")
    @RateLimiter(name = "cloud-payment-service", fallbackMethod = "rateLimiterFallback")
    public R ratelimit(@PathVariable("id") Integer id) {

        return R.ok().data(payFeignApi.bulkhead(id) + "ratelimit id:" + id + " \t " + IdUtil.simpleUUID());


    }

    private R rateLimiterFallback(Throwable t) {
        return R.failure(" threadpoolbulkhead ERROR");
    }


    @GetMapping("/micrometer/{id}")
    @RateLimiter(name = "cloud-payment-service", fallbackMethod = "rateLimiterFallback")
    public R micrometer(@PathVariable("id") Integer id) {

        return R.ok().data(payFeignApi.micrometer(id) + "micrometer id:" + id + " \t " + IdUtil.simpleUUID());


    }
}
